﻿package com.tim.framework.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;

/**
 * @author Tim.
 */
public class DatetimeUtil {
	/**
	 * 分钟对应毫秒数.
	 */
	public final static Long MINUTE = 1000 * 60L;
	/**
	 * 小时对应毫秒数.
	 */
	public final static Long HOUR = MINUTE * 60;
	/**
	 * 天对应毫秒数.
	 */
	public final static Long DAY = HOUR * 24;
	public final static String DATE_PATTERN = "yyyy-MM-dd";

	public final static String TIME_PATTERN = "HH:mm:ss";

	public final static String DATE_TIME_PATTERN = DATE_PATTERN + " "
			+ TIME_PATTERN;

	/**
	 * 将时间格式化为指定模式字符串.
	 * 
	 * @param date
	 *            转换的时间.
	 * @param formatStyle
	 *            格式化模式.
	 */
	public static String formatDate(Date date, String formatStyle) {
		if (date != null) {
			SimpleDateFormat sdf = new SimpleDateFormat(formatStyle);
			String formatDate = sdf.format(date);
			return formatDate;
		} else {
			return "";
		}

	}

	// TODO 确定方法用途
	public static final Date convertStringToDate(String pattern, Locale locale,
			TimeZone zone, String strDate) throws ParseException {
		if (locale == null)
			locale = Locale.getDefault();
		if (zone == null)
			zone = TimeZone.getDefault();
		SimpleDateFormat df = new SimpleDateFormat(pattern, locale);
		df.setTimeZone(zone);
		try {
			return df.parse(strDate);
		} catch (ParseException pe) {
			throw new ParseException(pe.getMessage(), pe.getErrorOffset());
		}
	}

	/**
	 * 将字符串转换为中国yyyy-MM-dd时间.
	 * 
	 * @param strDate
	 *            时间字符串.
	 */
	public static final Date convertStringToDate(String strDate) {
		Locale locale = Locale.CHINESE;
		try {
			return convertStringToDate(DATE_PATTERN, locale, null, strDate);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 将指定字符串转换为指定样式的时间.
	 * 
	 * @param strDate
	 *            时间字符串.
	 * @param sytle
	 *            时间格式化字符串.
	 */
	public static final Date convertStringToDate(String strDate, String sytle) {
		Locale locale = Locale.CHINESE;
		try {
			return convertStringToDate(sytle, locale, null, strDate);
		} catch (Exception e) {
			return null;
		}
	}

	// TODO 确认方法作用
	public static final String convertDateToString(String pattern,
			Locale locale, TimeZone zone, Date aDate) {
		if (locale == null)
			locale = Locale.getDefault();
		if (zone == null)
			zone = TimeZone.getDefault();
		SimpleDateFormat df = new SimpleDateFormat(pattern, locale);
		df.setTimeZone(zone);
		try {
			return df.format(aDate);
		} catch (Exception e) {
			return "";
		}
	}

	/**
	 * 将时间转换为指定格式的字符串.
	 * 
	 * @param pattern
	 *            格式化字符串.
	 * @param aDate
	 *            需要转换的时间.
	 */
	public static final String convertDateToString(String pattern, Date aDate) {
		Locale locale = Locale.CHINESE;
		return convertDateToString(pattern, locale, null, aDate);
	}

	/**
	 * 获取指定时间字符串(yyyy-MM-dd)当天0点时间.
	 * 
	 * @param beginDate
	 *            开始时间的日期.
	 */
	public static final Date getBeginDate(String beginDate) {
		Locale locale = Locale.CHINESE;
		try {
			return convertStringToDate("yyyy-MM-dd HH:mm:ss", locale, null,
					beginDate + " 00:00:00");
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 获取指定时间字符串(yyyy-MM-dd)当天最后一秒的时间.
	 * 
	 * @param endDate
	 *            结束时间的日期.
	 */
	public static final Date getEndDate(String endDate) {
		Locale locale = Locale.CHINESE;
		try {
			return convertStringToDate("yyyy-MM-dd HH:mm:ss", locale, null,
					endDate + " 23:59:59");
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 获取当前时间的中文yyyy年mm月dd日 星期X字符串.
	 */
	public static String getFullDateStr() {
		DateFormat format = DateFormat.getDateInstance(DateFormat.FULL,
				Locale.CHINESE);
		return format.format(new Date());
	}

	/**
	 * 计算两个日期之间相差的天数(受时间影响).
	 * 
	 * @param date1
	 *            时间1.
	 * @param date2
	 *            时间2.
	 */
	public static int diffdates(Date date1, Date date2) {
		Long diff = Math.abs(date1.getTime() - date2.getTime());
		return Integer.parseInt("" + (diff / DAY));
	}

	/**
	 * 计算两个日期之间相差的天数(受时间影响).
	 */
	public static int getDays(GregorianCalendar g1, GregorianCalendar g2) {
		return diffdates(g1.getTime(), g2.getTime());
	}

	/**
	 * 功能：将表示时间的字符串以给定的样式转化为java.util.Date类型
	 * 且多于或少于给定的时间多少小时（formatStyle和formatStr样式相同）
	 * 
	 * @param:formatStyle 要格式化的样式,如:yyyy-MM-dd HH:mm:ss
	 * @param:formatStr 待转化的字符串(表示的是时间)
	 * @param:hour 多于或少于的小时数(可正可负) 单位为小时
	 * @return java.util.Date
	 */
	public static Date formartDate(String formatStyle, String formatStr,
			int hour) {
		SimpleDateFormat format = new SimpleDateFormat(formatStyle,
				Locale.CHINA);
		try {
			Date date = new Date();
			date.setTime(format.parse(formatStr).getTime() + hour * HOUR);
			return date;
		} catch (Exception e) {
			// TODO 异常处理
			System.out.println(e.getMessage());
			return null;
		}
	}

	/**
	 * 获取指定时间间隔的时间.
	 * 
	 * @param date
	 *            指定开始时间(null，则为当前时间).
	 * @param spacing
	 *            时间间隔毫秒数(推荐使用DatetimeUtil中的常量，避免过多计算).
	 * @param num
	 *            时间间隔数.(可穿正负值，正值表示加上指定时间，负值表示减去指定时间).
	 */
	public static Date getAfterDate(Date date, Long spacing, int num) {
		if (date == null)
			date = new Date();
		return new Date(date.getTime() + num * spacing);
	}

	/**
	 * 获取前一小时时间.
	 */
	public static Date getPreHour(Date date) {
		return getAfterDate(date, HOUR, -1);
	}

	/**
	 * 获取下一小时时间.
	 */
	public static Date getNextHour(Date date) {
		return getAfterDate(date, HOUR, -1);
	}

	/**
	 * 获取昨天时间.
	 */
	public static Date getYesterday(Date date) {
		return getAfterDate(date, DAY, -1);
	}

	/**
	 * 获取明天.
	 */
	public static Date getTomorrowDate(Date date) {
		return getAfterDate(date, DAY, 1);
	}

	/**
	 * 获取上周.
	 */
	public static Date getLastWeek(Date date) {
		return getAfterDate(date, DAY, -7);
	}

	/**
	 * 获取下周.
	 */
	public static Date getNextWeek(Date date) {
		return getAfterDate(date, DAY, 7);
	}

	/**
	 * 获取指定时间的下个月.
	 */
	public static Date getNextMonth(Date date) {
		if (date == null)
			date = new Date();
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.clear();
		cal.setTime(date);
		cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
		cal.getTime();
		return cal.getTime();
	}

	/**
	 * 获取指定时间的上个月.
	 */
	public static Date getLastMonth(Date date) {
		if (date == null)
			date = new Date();
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.clear();
		cal.setTime(date);
		cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1);
		cal.getTime();
		return cal.getTime();
	}

	/**
	 * 获得指定时间的某月的第一天
	 */
	public static Date getMonthFirstDay(Date date) {
		int[] dateArr = getDateArray(date);
		String year = String.valueOf(dateArr[0]);
		String month = String.valueOf(dateArr[1]);
		month = month.length() == 1 ? "0" + month : month;
		Date retDate = convertStringToDate(year + month + "01", "yyyyMMdd");
		return retDate;
	}

	/**
	 * 获得指定时间的某月的最后一天
	 * 
	 * @param date
	 * @return
	 * 
	 */
	public static Date getMonthLastDay(Date date) {
		int[] dateArr = getDateArray(date);
		int year = dateArr[0];
		int month = dateArr[1];
		int maxDayOfMonth = getMaxDayOfMonth(year, month);
		String monStr = String.valueOf(month);
		monStr = monStr.length() == 1 ? "0" + monStr : monStr;
		Date retDate = convertStringToDate(String.valueOf(year)
				+ String.valueOf(monStr) + String.valueOf(maxDayOfMonth),
				"yyyyMMdd");
		return retDate;
	}

	/**
	 * 获取指定年和月中该月的最大天数
	 * 
	 * @param year
	 *            指定年
	 * @param month
	 *            指定月 1-12
	 * @return 该月最大天数
	 */
	public static int getMaxDayOfMonth(int year, int month) {
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.clear();
		cal.set(year, month - 1, 1);
		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 根据指定的年份和指定的第多少周序号得到该周的第一天和最后一天日期
	 * 
	 * @param year
	 *            指定的年份,如2006
	 * @param weekNo
	 *            指定年份中的第多少周,如37
	 * @return 该周的起始日期后该周的结束日期<br>
	 *         Date[0] 起始日期<br>
	 *         Date[1] 结束日期
	 */
	public static Date[] getGivenWeekDates(int year, int weekNo) {
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.clear();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.WEEK_OF_YEAR, weekNo);
		Date begin = cal.getTime();
		cal.add(Calendar.DAY_OF_YEAR, 6);
		Date end = cal.getTime();
		return new Date[] { begin, end };
	}

	/**
	 * 根据指定日期获取其在一年中的第多少周
	 * 
	 * @param date
	 *            指定的日期,为null默认为当时日期
	 * @return 当年的第多少周序号,如37
	 */
	public static int getWeekNo(Date date) {
		if (date == null)
			date = new Date();
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.clear();
		cal.setTime(date);
		return cal.get(Calendar.WEEK_OF_YEAR);
	}

	/**
	 * 获取指定时间的年份
	 * 
	 * @param date
	 *            指定时间
	 * @return 年份
	 */
	public static int getYear(Date date) {
		if (date == null)
			date = new Date();
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.clear();
		cal.setTime(date);
		return cal.get(Calendar.YEAR);
	}

	/**
	 * 格式化日期
	 * 
	 * @param date
	 *            被格式化的日期.
	 * @param style
	 *            显示的样式，如yyyy-MM-dd hh:mm:ss.SSS.
	 */
	public static String fmtDate(Date date, String style) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(style);
		return dateFormat.format(date);
	}

	/**
	 * 得到当前日期的年，月，日，小时，分钟，秒数.
	 */
	public static int[] getDateArray(Date date) {
		if (date == null)
			date = new Date();
		Calendar cal = Calendar
				.getInstance(TimeZone.getDefault(), Locale.CHINA);
		cal.setTime(date);
		int[] dateArr = new int[6];
		dateArr[0] = cal.get(Calendar.YEAR);
		dateArr[1] = cal.get(Calendar.MONTH) + 1;
		dateArr[2] = cal.get(Calendar.DATE);
		dateArr[3] = cal.get(Calendar.HOUR_OF_DAY);
		dateArr[4] = cal.get(Calendar.MINUTE);
		dateArr[5] = cal.get(Calendar.SECOND);
		return dateArr;
	}

	/**
	 * 获取指定时间(月份)的第一天和最后一天字符串数组.
	 * 
	 * @param date
	 *            指定的时间.
	 */
	public static String[] getMonFirstLastDays(Date date) {
		if (date == null)
			date = new Date();
		Date firstDay = getMonthFirstDay(date);
		Date lastDay = getMonthLastDay(date);
		return new String[] { convertDateToString("yyyyMMdd", firstDay),
				convertDateToString("yyyyMMdd", lastDay) };
	}

	/**
	 * 将字符串20080808 转换成 2008-08-08
	 */
	public static String getDateForm(String date) {
		if (StringUtils.isBlank(date) || date.length() != 8) {
			return "0000-00-00";
		}
		return date.substring(0, 4) + "-" + date.substring(4, 6) + "-"
				+ date.substring(6, 8);
	}

	/**
	 * 将字符串2008-08-08 转换成 20080808
	 */
	public static String getDateTo(String date) {
		if (StringUtils.isBlank(date) || date.length() != 10) {
			return "00000000";
		}
		return date.replaceAll("-", "");
	}
}
